package com.pan.kang.core;


import com.pan.kang.support.SpringContextUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.Arrays;

@Component
public class BaseDecoratorInterfaceFactory implements DecoratorInterfaceFactory {

    @Autowired
    private DecoratorMapping decoratorMapping;

    @Override
    public <T> T getDecoratorService(Class<T> decoratorService) {
        Class<?> targetInterface = decoratorMapping.getTargetInterface(decoratorService);
        Class<?> decoratorInterfaceImpl = decoratorMapping.getDecoratorInterfaceImpl(decoratorService);
        Object args = SpringContextUtil.getBean(targetInterface);
        Object instance;
        try {
            Constructor<?> constructor = Class.forName(decoratorInterfaceImpl.getName())
                    .getDeclaredConstructor(targetInterface);
            ReflectionUtils.makeAccessible(constructor);
            instance = constructor.newInstance(args);
            autowired(decoratorInterfaceImpl, instance);
        } catch (Exception exception) {
            throw new RuntimeException(exception);
        }
        return (T) new DecoratorProxy(instance).getProxy();
    }

    private void autowired(Class<?> decoratorInterfaceImpl, Object instance) {
        Field[] declaredFields = decoratorInterfaceImpl.getDeclaredFields();
        Arrays.stream(declaredFields)
                .filter(field -> field.isAnnotationPresent(Autowired.class))
                .forEach(field -> {
                    ReflectionUtils.makeAccessible(field);
                    Object bean = SpringContextUtil.getBean(field.getType());
                    ReflectionUtils.setField(field, instance, bean);
                });

        // 递归调用
        if (decoratorInterfaceImpl != Object.class) {
            this.autowired(decoratorInterfaceImpl.getSuperclass(), instance);
        }
    }
}
